﻿// -----------------------------------------------------------------------
// <copyright file="Content.cs" company="Zen Design Corp">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Zen.BlackBerry.Common
{
	using System.Collections.Generic;
	using System.IO;

	/// <summary>
	/// Abstract class that all types of content must extend.
	/// </summary>
	public abstract class Content
	{
		private Dictionary<string, List<string>> _headers;

		/// <summary>
		/// Gets a value indicating whether this instance is empty.
		/// </summary>
		/// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
		public abstract bool IsEmpty
		{
			get;
		}

		/// <summary>
		/// Gets or sets the type of the content.
		/// </summary>
		/// <value>The type of the content.</value>
		public string ContentType
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the header value for the header with the specified name.
		/// </summary>
		/// <param name="headerName">Name of the header.</param>
		/// <returns>
		/// The header value or null if the header was not found.
		/// </returns>
		public string GetHeader(string headerName)
		{
			IList<string> headers = GetHeaders(headerName);
			if (headers != null && headers.Count > 0)
			{
				return headers[0];
			}
			return null;
		}

		/// <summary>
		/// Gets the collection of header values of all headers having the
		/// specified name.
		/// </summary>
		/// <param name="headerName">Name of the header.</param>
		/// <returns>
		/// A collection of strings representing all the header values.
		/// </returns>
		public IList<string> GetHeaders(string headerName)
		{
			List<string> values = GetHeaderValues(headerName, false);
			if (values == null)
			{
				return null;
			}
			return values.AsReadOnly();
		}

		/// <summary>
		/// Adds the header name and value to the instance.
		/// </summary>
		/// <param name="headerName">Name of the header.</param>
		/// <param name="headerValue">The header value.</param>
		public void AddHeader(string headerName, string headerValue)
		{
			IList<string> values = GetHeaderValues(headerName, true);
			values.Add(headerValue);
		}

		/// <summary>
		/// For the associated header name, replaces any existing values with
		/// the value specified.
		/// </summary>
		/// <param name="headerName">Name of the header.</param>
		/// <param name="headerValue">The header value.</param>
		public void SetHeader(string headerName, string headerValue)
		{
			IList<string> values = GetHeaderValues(headerName, true);
			values.Clear();
			values.Add(headerValue);
		}

		/// <summary>
		/// Writes this instance to the specified <see cref="StreamWriter"/>.
		/// </summary>
		/// <param name="writer">The writer.</param>
		public abstract void WriteTo(StreamWriter writer);

		/// <summary>
		/// Writes the headers to the specified <see cref="StreamWriter"/>.
		/// </summary>
		/// <param name="writer">The writer.</param>
		public void WriteHeadersTo(StreamWriter writer)
		{
			writer.WriteLine(GetHeaderText("Content-Type", ContentType));
			if (_headers != null)
			{
				foreach (var pair in _headers)
				{
					writer.WriteLine(GetHeaderText(pair.Key, pair.Value));
				}
			}
			writer.Flush();
		}

		private static string GetHeaderText(string header, string value)
		{
			return string.Format("{0}: {1}", header, value);
		}

		private static string GetHeaderText(string header, IEnumerable<string> values)
		{
			return string.Format("{0}: {1}", header, string.Join(",", values));
		}

		private List<string> GetHeaderValues(string headerName, bool createIfMissing)
		{
			List<string> values = null;

			if (_headers == null && createIfMissing)
			{
				_headers = new Dictionary<string, List<string>>();
			}

			if (_headers == null ||
				!_headers.TryGetValue(headerName, out values))
			{
				if (createIfMissing)
				{
					values = new List<string>();
					_headers.Add(headerName, values);
				}
			}

			return values;
		}
	}
}
